package org.suwenqian.airoleplayingchatbackend.service;

import com.alibaba.nls.client.AccessToken;
import com.alibaba.nls.client.protocol.InputFormatEnum;
import com.alibaba.nls.client.protocol.NlsClient;
import com.alibaba.nls.client.protocol.OutputFormatEnum;
import com.alibaba.nls.client.protocol.SampleRateEnum;
import com.alibaba.nls.client.protocol.asr.SpeechRecognizer;
import com.alibaba.nls.client.protocol.asr.SpeechRecognizerListener;
import com.alibaba.nls.client.protocol.asr.SpeechRecognizerResponse;
import com.alibaba.nls.client.protocol.tts.SpeechSynthesizer;
import com.alibaba.nls.client.protocol.tts.SpeechSynthesizerListener;
import com.alibaba.nls.client.protocol.tts.SpeechSynthesizerResponse;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.concurrent.CompletableFuture;

@Service
public class AliyunTtsService {

    private static final Logger logger = LoggerFactory.getLogger(AliyunTtsService.class);

    @Value("${aliyun.access-key-id}")
    private String accessKeyId;

    @Value("${aliyun.access-key-secret}")
    private String accessKeySecret;

    @Value("${aliyun.tts-app-key}")
    private String appKey;

    private NlsClient nlsClient;

    @PostConstruct
    public void init() {
        try {
            AccessToken accessToken = new AccessToken(accessKeyId, accessKeySecret);
            accessToken.apply();
            logger.info("Obtained access token: {}", accessToken.getToken());
            nlsClient = new NlsClient(accessToken.getToken());
        } catch (Exception e) {
            logger.error("Failed to initialize NlsClient", e);
            throw new RuntimeException("Failed to initialize NlsClient", e);
        }
    }

    /**
     * 将文本合成为语音字节数组
     * @param text 要合成的文本（不超过300字符）
     * @param voice 发音人（如"xiaoyun", "siyue", "aiqi"等）
     * @param format 音频格式
     * @return 语音字节数组的CompletableFuture
     */
    @Async
    public CompletableFuture<byte[]> synthesizeSpeech(String text, String voice, OutputFormatEnum format) {
        CompletableFuture<byte[]> resultFuture = new CompletableFuture<>();
        ByteArrayOutputStream audioStream = new ByteArrayOutputStream();

        SpeechSynthesizerListener listener = new SpeechSynthesizerListener() {
            @Override
            public void onMessage(ByteBuffer message) {
                try {
                    byte[] bytesArray = new byte[message.remaining()];
                    message.get(bytesArray);
                    audioStream.write(bytesArray);
                } catch (IOException e) {
                    resultFuture.completeExceptionally(e);
                }
            }

            @Override
            public void onComplete(SpeechSynthesizerResponse response) {
                try {
                    audioStream.close();
                    if ("SynthesisCompleted".equals(response.getName())) {
                        resultFuture.complete(audioStream.toByteArray());
                    } else {
                        resultFuture.completeExceptionally(new RuntimeException("合成失败: " + response.getStatusText()));
                    }
                } catch (IOException e) {
                    resultFuture.completeExceptionally(e);
                }
            }

            @Override
            public void onFail(SpeechSynthesizerResponse response) {
                try {
                    audioStream.close();
                    resultFuture.completeExceptionally(new RuntimeException("合成失败: " + response.getStatusText()));
                } catch (IOException e) {
                    resultFuture.completeExceptionally(e);
                }
            }
        };

        try {
            SpeechSynthesizer synthesizer = new SpeechSynthesizer(nlsClient, listener);
            synthesizer.setAppKey(appKey);
            synthesizer.setText(text);
            synthesizer.setVoice(voice);
            synthesizer.setFormat(format);
            synthesizer.setSampleRate(SampleRateEnum.SAMPLE_RATE_16K);
            synthesizer.setVolume(50);
            synthesizer.setSpeechRate(0);
            synthesizer.setPitchRate(0);

            synthesizer.start();
            synthesizer.waitForComplete();
        } catch (Exception e) {
            resultFuture.completeExceptionally(e);
        }

        return resultFuture;
    }

    /**
     * 简化方法 - 使用默认参数合成中文语音
     */
    public CompletableFuture<byte[]> synthesizeChineseSpeech(String text) {
        return synthesizeSpeech(text, "xiaoyun", OutputFormatEnum.MP3);
    }

    /**
     * 语音识别功能
     * @param file 上传的语音文件（MultipartFile）
     * @param sampleRate 采样率（8000 或 16000）
     * @return 识别结果的CompletableFuture
     */
    @Async
    public CompletableFuture<String> recognizeSpeech(MultipartFile file, int sampleRate) {
        CompletableFuture<String> resultFuture = new CompletableFuture<>();

        SpeechRecognizerListener listener = new SpeechRecognizerListener() {
            @Override
            public void onRecognitionResultChanged(SpeechRecognizerResponse response) {
                logger.info("Intermediate result: {}", response.getRecognizedText());
            }

            @Override
            public void onRecognitionCompleted(SpeechRecognizerResponse response) {
                resultFuture.complete(response.getRecognizedText());
            }

            @Override
            public void onStarted(SpeechRecognizerResponse response) {
                logger.info("Recognition started with task_id: {}", response.getTaskId());
            }

            @Override
            public void onFail(SpeechRecognizerResponse response) {
                resultFuture.completeExceptionally(new RuntimeException("Recognition failed: " + response.getStatusText()));
            }
        };

        try {
            SpeechRecognizer recognizer = getSpeechRecognizer(sampleRate, listener);

            byte[] buffer = new byte[3200];
            int len;
            try (InputStream is = file.getInputStream()) {
                while ((len = is.read(buffer)) > 0) {
                    recognizer.send(buffer, len);
                    int deltaSleep = getSleepDelta(len, sampleRate);
                    Thread.sleep(deltaSleep);
                }
            } catch (IOException e) {
                resultFuture.completeExceptionally(e);
            }

            recognizer.stop();
        } catch (Exception e) {
            resultFuture.completeExceptionally(e);
        }

        return resultFuture;
    }

    private SpeechRecognizer getSpeechRecognizer(int sampleRate, SpeechRecognizerListener listener) throws Exception {
        SpeechRecognizer recognizer = new SpeechRecognizer(nlsClient, listener);
        recognizer.setAppKey(appKey);
        recognizer.setFormat(InputFormatEnum.PCM);
        if (sampleRate == 16000) {
            recognizer.setSampleRate(SampleRateEnum.SAMPLE_RATE_16K);
        } else if (sampleRate == 8000) {
            recognizer.setSampleRate(SampleRateEnum.SAMPLE_RATE_8K);
        }
        recognizer.setEnableIntermediateResult(true);

        recognizer.start();
        return recognizer;
    }

    /**
     * 根据二进制数据大小计算对应的同等语音长度
     * @param dataSize 数据大小
     * @param sampleRate 采样率
     * @return 睡眠时间（毫秒）
     */
    private int getSleepDelta(int dataSize, int sampleRate) {
        int sampleBytes = 16; // 仅支持16位采样
        int soundChannel = 1; // 仅支持单通道
        return (dataSize * 10 * 8000) / (160 * sampleRate);
    }

    @PreDestroy
    public void shutdown() {
        if (nlsClient != null) {
            nlsClient.shutdown();
            logger.info("NlsClient has been shut down");
        }
    }
}

